;
(function(angular) {
  var zppdirective = angular.module('mydirective', [])
  zppdirective.directive('myRestict', function() {
    return {
      restrict: 'EACM',
      priority: 1,
      template: '<div>我的优先级是1</div>'
    }
  })
  zppdirective.directive('myPriority', function() {
    return {
      restrict: 'EACM',
      priority: 2,
      template: '<div>我的优先级是2</div>'
    }
  })
  zppdirective.directive('myDirective1', function() {
    return {
      restrict: 'A',
      priority: 3,
      link: function(scope) {
        console.log('myDirective11111')
      }
    }
  })
  zppdirective.directive('myDirective2', function() {
    return {
      restrict: 'A',
      priority: 4,
      terminal: true,
      link: function(scope, el) {
        console.log('myDirective222222')
      }
    }
  })
  zppdirective.directive('myDirective3', function() {
    return {
      restrict: 'A',
      priority: 5,
      link: function(scope, el) {
        console.log('myDirective33333')
      }
    }
  })
  zppdirective.directive('myDirective4', function() {
    return {
      restrict: 'EA',
      template: '<div>我是一段模板字符串</div>'
    }
  })
  zppdirective.directive('myDirective5', function() {
    return {
      restrict: 'EA',
      templateUrl: 'app/views/module.html'
    }
  })
  // replace
  zppdirective.directive('myDirective6', function() {
    return {
      restrict: 'EA',
      replace: true,
      templateUrl: 'app/views/module.html',
    }
  })
  // scope
  zppdirective.directive('myScope1', function() {
    return {
      restrict: 'EA',
      scope: true,
      templateUrl: 'app/views/template/submain.html',
      controller: function($scope) {
        $scope.submain = '我是指令自己的内容'
      }
    }
  })
  zppdirective.directive('myScope2', function() {
    return {
      restrict: 'EA',
      scope: {
        // myChild: '@',  // 储存与myChild相关联的字符串
        // myModel: '=', // 将myModel指定对象或者变量绑定
        // myFun: '&'   // 将外部方法传递给这个方法
        a: '@myChild',
        b: '=myModel',
        c: '&myFun'
      },
      templateUrl: 'app/views/template/submain2.html',
    }
  })
  // transclude1
  zppdirective.directive('sidebox', function() {
    return {
      restrict: 'EA',
      scope: {
        title: '@',
      },
      transclude: true,
      templateUrl: 'app/views/template/subtransclude.html',

    }
  })
  // transclude2
  zppdirective.directive('mainBox', function() {
    return {
      restrict: 'EA',
      scope: {
        title: '@',
      },
      transclude: {
        'content': 'contentDirective',
        'menu': '?menuDirective'
      },
      templateUrl: 'app/views/template/subtransclude2.html',
    }
  })
  zppdirective.directive('contentDirective', function() {
    return {
      restrict: 'EA',
      template: '<div>我是内容指令的内容</div>'
    }
  })
  zppdirective.directive('menuDirective', function() {
    return {
      restrict: 'EA',
      template: '<div>我是菜单指令的内容</div>'
    }
  })
  // ctrl
  zppdirective.directive('myDirectiveController', function() {
    return {
      restrict: 'EA',
      controller: function($scope, $element, $attrs) {
        // 指令控制器的逻辑代码
        $scope.list = ['zs', 'ls', 'ww'];
      },
      templateUrl: 'app/views/template/ctrl.html'
    }
  })
  zppdirective.directive('myDirectiveControllerAs', function() {
    return {
      restrict: 'EA',
      controller: function($scope, $element, $attrs) {
        // 指令控制器的逻辑代码
        this.list = ['zs', 'ls', 'ww'];
        this.myClick = function() {
          alert('我被点击了')
        }
      },
      controllerAs: 'myCtrl',
      link: function(scope, ele, attrs, myCtrl) {
        ele.on('click', myCtrl.myClick);
      },
      templateUrl: 'app/views/template/ctrlAs.html'
    }
  })
  // require
  zppdirective.directive('myDirectiveRequire', function() {
    return {
      restrict: 'EA',
      transclude: true,
      controller: function($scope, $element, $attrs) {
        // 指令控制器的逻辑代码
        $scope.list = ['zs', 'ls', 'ww'];
        // 在这里把控制看成一个构造函数
        this.myClick = function() {
          console.log('我是requireChild的父亲节点')
        }
      },
      templateUrl: 'app/views/template/require.html'
    }
  })
  zppdirective.directive('requireChild', function() {
    return {
      restrict: 'EA',
      // 以数组的形式引入多个其他的指令
      require: ['^myDirectiveRequire', '?requireSibling', '?test'],
      // 这里的第四个参数是数组，因为require的取值是数组
      // 如果require的取值是字符串，这里就是一个object,不过也可能为null
      link: function(scope, ele, attr, myCtrl) {
        console.log(myCtrl);
        myCtrl[0].myClick();
        console.log(myCtrl[1].msg)
      }
    }
  })
  zppdirective.directive('requireSibling', function() {
    return {
      restrict: 'EA',
      controller: function($scope) {
        this.msg = '我是requireChild的兄弟指令'
      }
    }
  })
  zppdirective.directive('test', function() {
    return {
      restrict: 'E',
      controller: function() {
        this.test = '我是测试指令'
      }
    }
  })
  // compile
  zppdirective.directive('compileDom', function(){
            return {
              restrict: 'EA',
              replace: true,
              template: '<p>{{item.name}}</p>',
              // 定义了compile就不需要定义link,当compile返回一个方法这个方法就是link
              // tElement 正在执行该指令的当前dom元素的jquery对象
              // tAttrs 正在执行该指令的当前dom元素的属性
              compile: function(tElement, tAttrs, transclude){
                console.log('编译阶段开始执行 compileDom');
                // 改变当前元素的DOM结构
                tElement.append(angular.element('<span>我是添加进来的</span>'));
                return {
                  // pre:编译阶段执行
                  pre: function preLink(scope, iElement, iAttrs, controller) {
                    console.log('preLink... compileDom');
                  },
                  // post: 所有子元素指令的post都执行后执行
                  post: function postLink(scope, iElement, iAttrs, controller){
                    iElement.on('click', function(){
                      scope.item.name = 'click aaa'
                      scope.$apply();
                    })
                    console.log('postLink .... compileDom');
                  }

                };//return
                //  compile直接返回的一个方法，就是postLink
              },
              // 这个方法不会再执行了
              link: function(scope, ele, attrs, ctrl) {
                  console.log('我还会执行吗')
              }
            }
          })
  zppdirective.directive('compileDom2', function() {
              return {
                restrict: 'EA',
                replace: true,
                compile: function(ele, attr, trl) {
                    console.log('编译阶段开始执行 compileDom2');
                    return {
                      pre: function(scope, ele, attr, ctrl){
                        console.log('prelink .... compileDom2')
                      },
                      post: function(scope, ele, attr, ctrl) {
                        console.log('postlink ....compileDom2')
                      }
                    }
                }
              }
  })
  zppdirective.directive('compileDom3', function() {
              return {
                restrict: 'EA',
                replace: true,
                compile: function(ele, attr, trl) {
                    console.log('编译阶段开始执行 compileDom3');
                    return {
                      pre: function(scope, ele, attr, ctrl){
                        console.log('prelink .... compileDom3')
                      },
                      post: function(scope, ele, attr, ctrl) {
                        console.log('postlink ....compileDom3')
                      }
                    }
                }
              }
  })

  // NgModelController
  // 指令主要完成：可以指定几个常见的时间单位，并且能够输入数据。最终我们将得到对应的秒数
  zppdirective.directive('myModelDirective', function() {
    return {
      restrict: 'EA',
      replace: true,
      templateUrl: 'app/views/template/timeduration.html',
      scope: {},
      require: '^ngModel',
      controller: function($scope) {
        // $scope.num = '';
        // $scope.unit = '';
      },
      link: function(scope, ele, attrs, ngModelController){
        var multiplierMap = {
          seconds: 1,
          minutes: 60,
          hours: 3600,
          days: 86400
        };
        var multiplierTypes = ['seconds', 'minutes', 'hours', 'days'];
         // TODO
        console.log(ngModelController);

        // $viewValue 就是指令渲染模板所用的值。
        // $modelValue  是在控制器中流通的值。

        // $parsers 将$viewValue -> $modelValue
        // $formatters 将$modelValye -> $viewValue

        // $formatters接受一个数组
        // 数组是一系列方法，用于将modelValue转化成viewValue
        // 第一步，拿到$modelValue上的值，将对应的值添加到$viewValue中去
        ngModelController.$formatters.push(function(modelValue) {
          console.log(modelValue);
          var unit = 'seconds', num = 0, i, unitName;
          modelValue = parseInt(modelValue || 0, 10);
          for( i = multiplierTypes.length -1; i > 0; i--) {
            unitName = multiplierTypes[i];
            if(modelValue % multiplierMap[unitName] === 0) {
              unit = unitName;
              break;
            }
          }
          if(modelValue) {
            num = modelValue/ multiplierMap[unit];
          }
          return {
            unit: unit,
            num: num
          }

        });
        // 最后返回的对象就是$viewValue 的value

        // 第二步： 我们调用$render方法将$viewValue渲染到指令模板中去
        ngModelController.$render = function() {
          scope.unit = ngModelController.$viewValue.unit;
          scope.num = ngModelController.$viewValue.num;
        }

        // 第三步，通过 $wacth来监控指令模板中的num 和unit变量， 当其发生变化，更新$viewValue
        scope.$watch('unit + num', function() {
          // $setViewValue 用于更新viewValue
          ngModelController.$setViewValue({
            unit: scope.unit,
            num: scope.num
          })
        })
        // 第四步， 通过$parsers 将$viewValue -> $modelValue
        ngModelController.$parsers.push(function(viewValue) {
          console.log(viewValue)
          var unit = viewValue.unit;
          var num = viewValue.num;
          var multiplier;
          multiplier = multiplierMap[unit];
          return num * multiplier;
        })

      }
    }
  })



})(angular)
